package com.wenhao.lock;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 线程是一个单独的资源类
 * 没有任何的附属操作
 *
 * Synchronized 是内置的关键字， Lock 是一个类
 * Synchronized 无法获取锁的状态， Lock 可以判断是否获取到了锁
 * Synchronized 自动释放锁， Lock 必须石洞释放锁
 * Synchronized 阻塞， Lock 不一定会一直阻塞
 * Synchronized 可重入、非公平， Lock，可重入、可以判断、可以设置公平锁
 * Synchronized 适合少量的代码同步问题， Lock适合锁大量的同步代码
 *
 * @author Wenhao Tong
 * @create 2021-08-19 16:39
 */
public class LockDemo {
    public static void main(String[] args) {
        // 多线程共用一个资源类
        Ticket ticket = new Ticket();

        new Thread(() -> {
            while (ticket.getNumber()> 0) {
                ticket.sell();
            }
        },"A").start();

        new Thread(() -> {
            while (ticket.getNumber()> 0) {
                ticket.sell();
            }
        },"B").start();

        new Thread(() -> {
            while (ticket.getNumber()> 0) {
                ticket.sell();
            }
        },"B").start();
    }
}

/**
 * 资源类 OOP
 */
class Ticket {
    /**
     * 属性 方法
     */
    private int number = 30;

    /**
     * 默认非公平
     */
    private Lock lock = new ReentrantLock();

    public int getNumber(){
        return number;
    }

    /**
     * 买票的方法
     * synchronized 本质 队列 锁
     */
    public void sell (){
        // 先加锁
        lock.lock();
        try {
            // 业务代码
            if (number > 0) {
                System.out.println(Thread.currentThread().getName() + "还剩" + --number + "张票");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}
